package cn.jbolt.core.json;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.ParserConfig;
import com.alibaba.fastjson.parser.deserializer.ObjectDeserializer;
import com.alibaba.fastjson.serializer.ObjectSerializer;
import com.alibaba.fastjson.serializer.SerializeConfig;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.serializer.ToStringSerializer;
import com.jfinal.json.FastJsonRecordSerializer;
import com.jfinal.json.Json;
import com.jfinal.plugin.activerecord.Record;

import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.sql.Time;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

/**
 * JBolt自定义FastJson
 *
 * @ClassName: JBoltFastJson
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2020年10月8日
 */
public class JBoltFastJson extends Json {
	private static Set<SerializerFeature> serializerFeatureSet = new HashSet<>();
	private static SerializerFeature[] serializerFeatures;
	public static void init(){
		// 支持序列化 ActiveRecord 的 Record 类型
		addSerializer(Record.class, new FastJsonRecordSerializer());
		// Long转String 防止js 精度丢失
		addSerializer(Long.class, ToStringSerializer.instance);
		addSerializer(Long.TYPE, ToStringSerializer.instance);
		// BigDecimal 智能 转String 防止js 精度丢失
//		addSerializer(BigDecimal.class,BigDecimalSerializer.instance);
		// time 反序列化处理
		addDeserializer(Time.class, JBoltSqlTimeDeserializer.instance);
		// 完全禁用 autoType，提升安全性
		try {
			ParserConfig.getGlobalInstance().setSafeMode(true);
		} catch (Exception e) {
			// 老版本 fastjson 无 setSafeMode(boolean) 方法
			com.jfinal.kit.LogKit.logNothing(e);
		}
		//添加序列化特性 格式化时间
		addSerializerFeature(SerializerFeature.WriteDateUseDateFormat);
		//添加序列化特性 消除对同一对象循环引用的问题
		addSerializerFeature(SerializerFeature.DisableCircularReferenceDetect);
	}

	/**
	 * 添加新的SerializerFeature
	 * @param newSerializerFeatures
	 */
	public static void addSerializerFeature(SerializerFeature... newSerializerFeatures){
		serializerFeatureSet.addAll(Arrays.asList(newSerializerFeatures));
		serializerFeatures = serializerFeatureSet.toArray(new SerializerFeature[0]);
	}
	/**
	 * 处理null
	 * 默认所有null都处理
	 * Boolean转false
	 * list转[]
	 * Number转0
	 * String转 “”
	 */
	public static void processNullValueDefaultFeatures(){
		addSerializerFeature(
				SerializerFeature.WriteMapNullValue,
				SerializerFeature.WriteNullBooleanAsFalse,
				SerializerFeature.WriteNullListAsEmpty,
				SerializerFeature.WriteNullNumberAsZero,
				SerializerFeature.WriteNullStringAsEmpty
				);
	}

	/**
	 * 处理null显示
	 */
	public static void writeMapNullValue(){
		addSerializerFeature(SerializerFeature.WriteMapNullValue);
	}
	/**
	 * 处理Boolean null转false
	 */
	public static void writeNullBooleanAsFalse(){
		addSerializerFeature(SerializerFeature.WriteNullBooleanAsFalse);
	}
	/**
	 * 处理list null转[]
	 */
	public static void writeNullListAsEmpty(){
		addSerializerFeature(SerializerFeature.WriteNullListAsEmpty);
	}
	/**
	 * 处理数字 null转0
	 */
	public static void writeNullNumberAsZero(){
		addSerializerFeature(SerializerFeature.WriteNullNumberAsZero);
	}
	/**
	 * 处理字符串 null转 “”
	 */
	public static void writeNullStringAsEmpty(){
		addSerializerFeature(SerializerFeature.WriteNullStringAsEmpty);
	}

	@Override
	public String toJson(Object object) {
		// 优先使用对象级的属性 datePattern, 然后才是全局性的 defaultDatePattern
		String dp = datePattern != null ? datePattern : getDefaultDatePattern();
		return JSON.toJSONStringWithDateFormat(object, dp,serializerFeatures);
	}

	@Override
	public <T> T parse(String jsonString, Class<T> type) {
		return JSON.parseObject(jsonString, type);
	}

	/**
	 * 添加序列化配置
	 *
	 * @param type
	 * @param value
	 */
	public static void addSerializer(Type type, ObjectSerializer value) {
		SerializeConfig.getGlobalInstance().put(type, value);
	}

	/**
	 * 添加反序列化配置
	 *
	 * @param type
	 * @param value
	 */
	public static void addDeserializer(Type type, ObjectDeserializer value) {
		ParserConfig.getGlobalInstance().putDeserializer(type, value);
	}
}
